Contents
Introducción
Este tutorial explica, paso a paso y con todo lujo de detalles, cómo crear un bloque de Gutenberg que permita subir o seleccionar archivos y guardarlos en la Biblioteca de Medios de WordPress usando JavaScript (React APIs de WP). Incluye ejemplos de código listos para usar: el PHP necesario para registrar y encolar los scripts del bloque, el JavaScript del bloque (usando MediaUpload y un media frame personalizado) y una alternativa avanzada mediante la REST API para subir archivos directamente. También se tratan seguridad, permisos y buenas prácticas.
Requisitos y buenas prácticas
- WordPress 5.0 (Gutenberg integrado) o cualquier instalación con soporte de bloques.
- Conocimientos básicos de JS (ESNext/JSX) y PHP.
- Uso recomendado de @wordpress/scripts para build (wp-scripts).
- Comprueba que el usuario que vaya a subir archivos tenga la capacidad upload_files.
- Usar nonces para llamadas REST seguras (wp_create_nonce(wp_rest)).
Estructura mínima del plugin/proyecto
Ejemplo de estructura recomendada:
- my-media-block/
- my-media-block.php (archivo principal del plugin)
- src/
- block.js (código del bloque)
- build/
- block.js (archivo resultante tras build)
- package.json
1) Archivo PHP principal: registrar y encolar
En el archivo principal del plugin registramos el script del bloque y pasamos datos útiles (por ejemplo nonce y siteUrl) para llamadas REST. A continuación un ejemplo mínimo.
wp_create_nonce( wp_rest ), siteUrl => get_site_url(), ) ) register_block_type( bmu/media-uploader, array( editor_script => bmu-block, ) ) } add_action( init, bmu_register_block )
Render dinámico opcional
Si quieres que el bloque renderice en el frontend a partir de los atributos puedes registrarlo con render_callback. Ejemplo sencillo:
function bmu_render_block( attributes ) { id = isset( attributes[mediaId] ) ? intval( attributes[mediaId] ) : 0 url = isset( attributes[mediaUrl] ) ? esc_url( attributes[mediaUrl] ) : name = isset( attributes[filename] ) ? esc_html( attributes[filename] ) : if ( ! id ! url ) { returnNo hay archivo seleccionado.
} return sprintf( , url, name ? name : Descargar archivo ) } register_block_type( bmu/media-uploader, array( editor_script => bmu-block, render_callback => bmu_render_block, ) )
2) package.json mínimo para build
Si usas @wordpress/scripts, este package.json proporciona scripts para build y start durante el desarrollo.
{ name: bmu, version: 1.0.0, scripts: { build: wp-scripts build, start: wp-scripts start }, devDependencies: { @wordpress/scripts: ^24.0.0 } }
3) Código del bloque (JS) – ejemplo usando MediaUpload
La forma más sencilla para permitir que un usuario suba o seleccione un archivo es usar el componente MediaUpload de @wordpress/block-editor. Este componente abre la ventana de medios de WP y permite subir o elegir archivos. Al seleccionar devuelve el objeto de adjunto.
import { registerBlockType } from @wordpress/blocks import { MediaUpload, MediaUploadCheck } from @wordpress/block-editor import { Button } from @wordpress/components import { Fragment } from @wordpress/element registerBlockType( bmu/media-uploader, { title: Subir archivo a Media Library, category: media, attributes: { mediaId: { type: number }, mediaUrl: { type: string }, filename: { type: string } }, edit: ( { attributes, setAttributes } ) => { const { mediaId, mediaUrl, filename } = attributes const onSelectMedia = ( media ) => { if ( ! media ! media.id ) return setAttributes({ mediaId: media.id, mediaUrl: media.url media.sizes?.full?.url media.source_url, filename: media.title?.raw media.filename }) } const removeMedia = () => { setAttributes({ mediaId: undefined, mediaUrl: undefined, filename: undefined }) } return () }, save: () => { return null // se usa render_callback o atributos guardados. } } ) { mediaUrl ? () : (![]()
Archivo: { filename } (ID: { mediaId })
) } ( ) } />
Notas sobre MediaUpload
- MediaUpload permite que el usuario suba (pestaña Subir archivos) o seleccione de la biblioteca.
- El objeto devuelto en onSelect contiene id, url/source_url, title, filename, mime_type, sizes, etc.
- Usa allowedTypes para filtrar tipos MIME (por ejemplo image o [application/pdf]).
4) Alternativa: usar un media frame personalizado (window.wp.media)
Si necesitas más control (por ejemplo configurar estado, multiple, título, botones o escuchar eventos concretos), puedes abrir un frame personalizado con window.wp.media. Este ejemplo abre el modal y obtiene el archivo seleccionado o subido.
// abrir un frame personalizado: const openMediaFrame = () => { const wpMedia = window.wp window.wp.media if ( ! wpMedia ) return const frame = wpMedia({ title: Seleccionar o subir archivo, button: { text: Usar este archivo }, multiple: false }) frame.on( select, () => { const selection = frame.state().get(selection).first().toJSON() // selection contiene id, url, filename, etc. setAttributes({ mediaId: selection.id, mediaUrl: selection.url selection.source_url, filename: selection.title selection.filename }) }) frame.open() }
5) Opción avanzada: subir directamente mediante la REST API (/wp/v2/media)
Si quieres subir el archivo desde el cliente sin usar el modal (por ejemplo arrastrando y soltando un archivo y subirlo automáticamente), usa la ruta /wp/v2/media. Es imprescindible enviar la cabecera X-WP-Nonce para autenticar la petición. En el ejemplo siguiente se asume que en el script hemos inyectado bmuData.nonce y bmuData.siteUrl.
// subir archivo directamente a /wp/v2/media async function uploadFileDirectly( file ) { const form = new FormData() form.append( file, file, file.name ) const response = await fetch( bmuData.siteUrl /wp-json/wp/v2/media, { method: POST, headers: { X-WP-Nonce: bmuData.nonce }, body: form } ) if ( ! response.ok ) { const err = await response.text() throw new Error( Error subiendo: err ) } const json = await response.json() // json.id, json.source_url return json }
Puntos importantes sobre la REST API
- El usuario que realice la subida debe tener la capacidad upload_files.
- Controla los tipos MIME y tamaños en el servidor si es necesario.
- Comprueba y gestiona errores (código 400/403/413, etc.).
6) Guardar atributos y renderizado
Recomendación: guarda en los atributos al menos mediaId (ID del adjunto) y mediaUrl (URL). El ID permite realizar operaciones adicionales (por ejemplo actualizar la información del adjunto). Para el frontend puedes usar render_callback en PHP (ver ejemplo de PHP arriba) o guardar un HTML estático en save().
7) Permisos, seguridad y validaciones
- Usa nonces: genera con wp_create_nonce(wp_rest) y pásalo con wp_localize_script para las llamadas REST.
- Comprueba capacidades del usuario (current_user_can(upload_files)) si haces lógica en PHP.
- Valida los tipos MIME y tamaños en el servidor (no confíes solo en el cliente).
- Escapa salidas en PHP con esc_url() / esc_html() si renderizas en el servidor.
8) Errores comunes y cómo solucionarlos
- El modal no se abre: asegúrate de que window.wp.media está cargado en editor debe estar presente si las dependencias están bien encoladas.
- 403 en la subida REST: nonce inválido o falta capacidad revisa X-WP-Nonce y current_user_can.
- URL incorrecta tras seleccionar: revisa las propiedades del objeto devuelto (source_url, url, sizes).
- Permisos CORS en instalaciones headless: tendrás que configurar cabeceras o auth adecuada.
9) Tips finales y mejoras
- Soporta múltiples archivos configurando multiple={true} y guardando un array de IDs/URLs.
- Muestra previsualizaciones usando los tamaños disponibles en media.sizes.
- Permite reordenar y eliminar archivos si es una galería/colección.
- Considera crear un control personalizado que combine drag drop subida vía REST y posterior selección por ID.
- Versiona y cachea correctamente el script en PHP usando filemtime para busting en producción.
Recapitulación rápida
- La forma más simple: usar MediaUpload para abrir la ventana de medios (soporta subida automática).
- Para control extra: usar window.wp.media para crear frames personalizados.
- Para subir sin UI: usar la ruta REST /wp/v2/media con nonce y FormData.
- Siempre valida permisos y escapa las salidas cuando renderices en el frontend.
Enlaces útiles
Conclusión
Con estas piezas tienes todo lo necesario para crear un bloque de Gutenberg que permita subir y seleccionar archivos en la Biblioteca de Medios mediante JS. Elige la aproximación (MediaUpload, media frame personalizado o REST API) que mejor se adapte a tu caso de uso, y aplica las comprobaciones de seguridad y validaciones descritas para garantizar robustez en producción.
|
Acepto donaciones de BAT's mediante el navegador Brave 🙂 |